/*************************************************************************
 * Copyright 2008 David Almilli
 *  
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 *  
 *     http://www.apache.org/licenses/LICENSE-2.0 
 *      
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 **************************************************************************/
package com.almilli.catnip.web;

import com.tivo.hme.interfaces.IArgumentList;
import java.util.ArrayList;
import java.util.List;

/**
 * The <code>ArgumentList</code> class is an implementation of IArgumentList that can parse
 * arguments from a command line string.  Each argument is separated by spaces.  You can quote an
 * argument so that it can include spaces.
 * @author s2kdave
 */
public class ArgumentList implements IArgumentList {
    
    private List<String> args;
    
    public ArgumentList(String args) {
        if (args != null) {
            this.args = parse(args);
        } else {
            this.args = new ArrayList<String>();
        }
    }
    
    private List<String> parse(String args) {
        List<String> list = new ArrayList<String>();
        StringBuilder sb = new StringBuilder();
        
        boolean quote = false;
        for (int i=0; i < args.length(); i++) {
            char ch = args.charAt(i);
            if (ch == '\\') {
                if (i+1 < args.length()) {
                    char next = args.charAt(i+1);
                    if (next == '\\' || next == '\"') {
                        sb.append(next);
                        continue;
                    }
                }
            } else if (ch == '\"') {
                quote = !quote;
                continue;
            }
            
            if (!quote && Character.isWhitespace(ch)) {
                //commit the current element
                if (sb.length() > 0) {
                    list.add(sb.toString());
                    sb.setLength(0);
                }
            } else {
                sb.append(ch);
            }
        }
        //commit the last entry
        if (sb.length() > 0) {
            list.add(sb.toString());
            sb.setLength(0);
        }
        return list;
    }

    public void checkForIllegalFlags() {
        for (String arg : args) {
            if (arg.startsWith("-")) {
                throw new BadArgumentException("don't understand " + arg);
            }
        }
    }

    public boolean getBoolean(String key) {
        int index = args.indexOf(key);
        if (index == -1) {
            return false;
        }
        args.remove(index);
        return true;
    }

    public int getInt(String key) {
        try {
            return Integer.parseInt(getValue(key));
        } catch (NumberFormatException e) {
            throw new BadArgumentException(key + " should be a number");
        }
    }

    public int getInt(String key, int defaultValue) {
        String value = getValue(key, null);
        if (value == null) {
            return defaultValue;
        }
        
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new BadArgumentException(key + " should be a number");
        }
    }

    public String[] getRemainingArgs() {
        String[] remaining = new String[args.size()];
        args.toArray(remaining);
        return remaining;
    }

    public int getRemainingCount() {
        return args.size();
    }

    public String getValue(String key) {
        String value = getValue(key, null);
        if (value == null) {
            throw new BadArgumentException(key + " is required");
        }
        return value;
    }

    public String getValue(String key, String defaultValue) {
        int index = args.indexOf(key);
        if (index == -1) {
            return defaultValue;
        }
        args.remove(index);

        if (index == args.size()) {
            throw new BadArgumentException(key + " needs a parameter");
        }

        String value = args.get(index);
        if (value.startsWith("-")) {
            throw new BadArgumentException(key + " needs a parameter");
        }
        args.remove(index);
        
        return value;
    }

    public String shift() {
        if (args.size() == 0) {
            throw new BadArgumentException("missing argument");
        }
        String value = args.remove(0);
        return value;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (String arg : args) {
            if (sb.length() != 0) {
                sb.append(' ');
            }
            if (arg.indexOf(' ') != -1 && !arg.startsWith("\"")) {
                sb.append('"');
                sb.append(arg);
                sb.append('"');                
            } else {
                sb.append(arg);
            }
        }
        return sb.toString();
    }

}
